<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
    <title>jsUri tests</title>
    <script type="text/javascript" src="jsuri.js"></script>
    <script type="text/javascript" src="jsunit/app/jsUnitCore.js"></script>
    <script type="text/javascript">

        // any quasi-valid uri should survive parsing and re-stringification, cloning and re-stringification of the clone
        function _testSimpleUri(s) {
            var uri = new jsUri(s);
            var expectedResponse = (arguments.length == 0) ? '' : s;
            assertEquals('Uri stringification should match the original', expectedResponse, uri.toString());
            assertEquals('Uri clone stringification should match the original', expectedResponse, uri.clone().toString());
        }

        function testSimpleEmptyConstructor() { _testSimpleUri(); }
        function testSimpleEmptyUri() { _testSimpleUri(''); }
        function testSimpleRelativeUri() { _testSimpleUri('/'); }
        function testSimpleRelativeDirectoryUri() { _testSimpleUri('tutorial1/'); }
        function testSimpleRelativeDirectory2Uri() { _testSimpleUri('/experts/'); }
        function testSimpleRelativeWithFilenameUri() { _testSimpleUri('/index.html'); }
        function testSimpleRelativeWithDirectoryAndFilenameUri() { _testSimpleUri('tutorial1/2.html'); }
        function testSimpleRelativeParentDirectoryUri() { _testSimpleUri('../'); }
        function testSimpleRelativeSiblingDirectoryUri() { _testSimpleUri('../experts/'); }
        function testSimpleRelativeGreatGrandparentDirectoryUri() { _testSimpleUri('../../../'); }
        function testSimpleRelativeCurrentDirectoryUri() { _testSimpleUri('./'); }
        function testSimpleRelativeCurrentDirectorySiblingDocUri() { _testSimpleUri('./test.html'); }
        function testSimpleDomain() { _testSimpleUri('www.test.com'); }
        function testSimpleAbsoluteUri() { _testSimpleUri('http://www.test.com/index.html'); }
        function testSimpleHttpsUri() { _testSimpleUri('http://www.test.com/index.html'); }
        function testSimpleCustomPortUri() { _testSimpleUri('http://www.test.com:8080/index.html'); }
        function testSimpleHttpsCustomPortUri() { _testSimpleUri('https://www.test.com:43443'); }
        function testSimpleRelativeWithAnchorUri() { _testSimpleUri('/index.html#content'); }
        function testSimpleAbsoluteWithAnchorUri() { _testSimpleUri('http://www.test.com/index.html#content'); }
        function testSimpleRelativeWithParamsUri() { _testSimpleUri('/index.html?a=1&b=2'); }
        function testSimpleAbsoluteWithParamsUri() { _testSimpleUri('http://www.test.com/index.html?a=1&b=2'); }
        function testSimpleAbsoluteWithParamsAndAnchorUri() { _testSimpleUri('http://www.test.com/index.html?a=1&b=2#content'); }
        function testSimpleWithMultipleParamValuesUri() { _testSimpleUri('http://www.test.com/index.html?arr=1&arr=2&arr=3&arr=3&b=2'); }
        function testSimpleWithBlankParamValuesUri() { _testSimpleUri('http://www.test.com/index.html?arr=1&arr=&arr=2'); }
        function testSimpleWithoutSchemeUri() { _testSimpleUri('//www.test.com/'); }

        /*
            uri manipulation tests
        */

        function testReplacingProtocol() {
            var uri = new jsUri('http://www.test.com/index.html?arr=1&arr=&arr=2');
            uri.protocol('https');
            assertEquals('Protocol should switch to https', 'https://www.test.com/index.html?arr=1&arr=&arr=2', uri.toString());
        }

        function testReplacingProtocolWithColon() {
            var uri = new jsUri('http://www.test.com/index.html?arr=1&arr=&arr=2');
            uri.protocol('https:');
            assertEquals('There should not be a double colon', 'https://www.test.com/index.html?arr=1&arr=&arr=2', uri.toString());
        }

        function testDisablingHasAuthorityPrefix() {
            var uri = new jsUri('//test.com/index.html');
            uri.hasAuthorityPrefix(false);
            assertEquals('The authority prefix slashes (//) should be removed', 'test.com/index.html', uri.toString());
        }

        function testDeletingProtocolKeepsAuthorityPrefix() {
            var uri = new jsUri('https://test.com/index.html');
            uri.protocol(null);
            assertEquals('Authority prefix (//) slashes should remain intact', '//test.com/index.html', uri.toString());
        }

        function testDeletingProtocolAndHasAuthorityPrefix() {
            var uri = new jsUri('https://test.com/index.html');
            uri.protocol(null);
            uri.hasAuthorityPrefix(false);
            assertEquals('Authority prefix (//) slashes should be suppressed', 'test.com/index.html', uri.toString());
        }

        function testDisablingHasAuthorityPrefixWithProtocolConflict() {
            var uri = new jsUri('http://www.test.com/');
            uri.hasAuthorityPrefix(false);
            assertEquals('Authority prefix (//) slashes should remain intact', 'http://www.test.com/', uri.toString());
        }

        function testDisablingProtocolAndHasAuthorityPrefix() {
            var uri = new jsUri('http://www.test.com/');
            uri.protocol(null);
            uri.hasAuthorityPrefix(false);
            assertEquals('Authority prefix should be stripped', 'www.test.com/', uri.toString());
        }

        function testAddingUserInfo() {
            var uri = new jsUri('https://test.com/index.html');
            uri.userInfo('username:password');
            assertEquals('The dummy login information should be included in the uri', 'https://username:password@test.com/index.html', uri.toString());
        }

        function testAddingUserInfoWithTrailing() {
            var uri = new jsUri('https://test.com/index.html');
            uri.userInfo('username:password@');
            assertEquals('The superfluous trailing symbol should be stripped', 'https://username:password@test.com/index.html', uri.toString());
        }

        function testAddingHostnameRelative() {
            var uri = new jsUri('/index.html');
            uri.host('wherever.com');
            assertEquals('The hostname should be added to the uri', 'wherever.com/index.html', uri.toString());
        }

        function testChangingHostnameRelative() {
            var uri = new jsUri('test.com/index.html');
            uri.host('wherever.com');
            assertEquals('The hostname should be added to the uri', 'wherever.com/index.html', uri.toString());
        }

        function testChangingHostnameAbsolute() {
            var uri = new jsUri('http://test.com/index.html');
            uri.host('wherever.com');
            assertEquals('The hostname should be changed to whatever.com', 'http://wherever.com/index.html', uri.toString());
        }

        function testAddingPortRelativeWithoutHost() {
            var uri = new jsUri('/index.html');
            uri.port(8080);
            assertEquals('The port will not show without a host', '/index.html', uri.toString());
        }

        function testAddingPortAndHostRelative() {
            var uri = new jsUri('/index.html');
            uri.port(8080);
            uri.host('test.com');
            assertEquals('The port will not show without a host', 'test.com:8080/index.html', uri.toString());
        }

        function testChangingPortRelative() {
            var uri = new jsUri('test.com:80/index.html');
            uri.port(8080);
            assertEquals('The port should be changed to 8080', 'test.com:8080/index.html', uri.toString());
        }

        function testChangingPortAbsolute() {
            var uri = new jsUri('http://test.com/index.html');
            uri.port(8080);
            assertEquals('The hostname should be changed to whatever.com', 'http://test.com:8080/index.html', uri.toString());
        }

        function testAddingAPath() {
            var uri = new jsUri('www.test.com');
            uri.path('/some/article.html');
            assertEquals('The path should be appended to the uri', 'www.test.com/some/article.html', uri.toString());
        }
        
        function testChangingPath() {
            var uri = new jsUri('http://www.test.com/news/latest.html');
            uri.path('/contact-us.html');
            assertEquals('The path be changed', 'http://www.test.com/contact-us.html', uri.toString());
        }

        function testNullifyingPath() {
            var uri = new jsUri('http://www.test.com/news/latest.html');
            uri.path(null);
            assertEquals('The path be removed', 'http://www.test.com', uri.toString());
        }

        function testEmptyPath() {
            var uri = new jsUri('http://www.test.com/news/latest.html');
            uri.path('');
            assertEquals('The path be removed', 'http://www.test.com', uri.toString());
        }

        function testAddingAQueryToNothing() {
            var uri = new jsUri('');
            uri.query('this=that&something=else');
            assertEquals('The query string, question mark and slash should all be added to the url', '?this=that&something=else', uri.toString());
        }

        function testAddingAQueryToARelativePath() {
            var uri = new jsUri('/some/file.html');
            uri.query('this=that&something=else');
            assertEquals('The query string, question mark and slash should all be added to the url', '/some/file.html?this=that&something=else', uri.toString());
        }

        function testAddingAQueryToADomain() {
            var uri = new jsUri('www.test.com');
            uri.query('this=that&something=else');
            assertEquals('The query string, question mark and slash should all be added to the url', 'www.test.com/?this=that&something=else', uri.toString());
        }

        function testSwappingQuery() {
            var uri = new jsUri('www.test.com?this=that&a=1&b=2;c=3');
            uri.query('one=1&two=2');
            assertEquals('The query string should be replaced', 'www.test.com/?one=1&two=2', uri.toString());
        }

        function testNullifyingQuery() {
            var uri = new jsUri('www.test.com?this=that&a=1&b=2;c=3');
            uri.query(null);
            assertEquals('The query string and path placeholder should be removed', 'www.test.com', uri.toString());
        }

        function testEmptyingQuery() {
            var uri = new jsUri('www.test.com?this=that&a=1&b=2;c=3');
            uri.query('');
            assertEquals('The query string and path placeholder should be removed', 'www.test.com', uri.toString());
        }

        function testAddingAnchorToDomain() {
            var uri = new jsUri('www.test.com');
            uri.anchor('content');
            assertEquals('The anchor and path placeholder should be added', 'www.test.com/#content', uri.toString());
        }

        function testAddingAnchorWithHash() {
            var uri = new jsUri('www.test.com');
            uri.anchor('#content');
            assertEquals('The anchor and path placeholder should be added but no double hash', 'www.test.com/#content', uri.toString());
        }

        function testAddingAnchorToPath() {
            var uri = new jsUri('a/b/c/123.html');
            uri.anchor('content');
            assertEquals('The anchor should be added', 'a/b/c/123.html#content', uri.toString());
        }

        function testChangingAnchor() {
            var uri = new jsUri('a/b/c/123.html#content');
            uri.anchor('footer');
            assertEquals('The anchor should be changed', 'a/b/c/123.html#footer', uri.toString());
        }

        function testEmptyingAnchor() {
            var uri = new jsUri('a/b/c/123.html#content');
            uri.anchor('');
            assertEquals('The anchor should be removed', 'a/b/c/123.html', uri.toString());
        }


        /*
            fluent setters test
        */

        function testFluentAddition() {
            var uri = new jsUri('www.yahoo.com');
            uri.setPath('/index.html').setAnchor('content');
            assertEquals('The uri should now contain path and anchor elements', 'www.yahoo.com/index.html#content', uri.toString());
        }

        function testFluentReplacement() {
            var uri = new jsUri('http://www.test.com');
            uri.setHost('www.yahoo.com').setProtocol('https');
            assertEquals('The uri should have been properly updated', 'https://www.yahoo.com', uri.toString());
        }

        function testFluentConstruction() {
            var uri = new jsUri('')
                .setPath('/index.html')
                .setAnchor('content')
                .setHost('www.test.com')
                .setPort(8080)
                .setUserInfo('username:password')
                .setProtocol('https')
                .setQuery('this=that&some=thing');

            assertEquals('The uri should now contain all elements', 'https://username:password@www.test.com:8080/index.html?this=that&some=thing#content', uri.toString());
        }

        function testFluentDestruction() {
            var uri = new jsUri('https://username:password@www.test.com:8080/index.html?this=that&some=thing#content')
                .setPath(null)
                .setAnchor(null)
                .setHost(null)
                .setPort(null)
                .setUserInfo(null)
                .setProtocol(null)
                .setQuery(null);

            assertEquals('The uri should now be empty', '', uri.toString());
        }

        function testHostQuerySeparator() {
            var uri = new jsUri('www.test.com?q=search');
            assertEquals('Uri should contain a separator slash', 'www.test.com/?q=search', uri.toString());
        }

        
        /*
            query manipulation tests
        */

        function testGettingParamValue() {
            var uri = new jsUri('?a=1&a=2&b=3&b=4&c=567');
            assertEquals('a should match', '1', uri.getQueryParamValue('a'));
            assertEquals('b should match', '3', uri.getQueryParamValue('b'));
            assertEquals('c should match', '567', uri.getQueryParamValue('c'));
        }

        function testGettingParamValues() {
            var uri = new jsUri('?a=1&a=2&b=3&b=4&c=567');
            assertEquals('a:0 should match', '1', uri.getQueryParamValues('a')[0]);
            assertEquals('a:1 should match', '2', uri.getQueryParamValues('a')[1]);
            assertEquals('b:0 should match', '3', uri.getQueryParamValues('b')[0]);
            assertEquals('b:1 should match', '4', uri.getQueryParamValues('b')[1]);
            assertEquals('c:0 should match', '567', uri.getQueryParamValues('c')[0]);
        }

        function testAddingParamToBlank() {
            var uri = new jsUri('').addQueryParam('q', 'books');
            assertEquals('The url should be just a query string', '?q=books', uri.toString());
        }

        function testAddingParamToAbsolute() {
            var uri = new jsUri('http://www.microsoft.com').addQueryParam('testing', '123').addQueryParam('one', 1);
            assertEquals('The url should be just a query string', 'http://www.microsoft.com/?testing=123&one=1', uri.toString());
        }

        function testdeleteQueryParamName() {
            var uri = new jsUri('test.com?a=1&b=2&c=3&a=eh').deleteQueryParam('b');
            assertEquals('The query string should not contain the b=2 param', 'test.com/?a=1&c=3&a=eh', uri.toString());
        }

        function testdeleteQueryParamNameValue() {
            var uri = new jsUri('test.com?a=1&b=2&c=3&a=eh').deleteQueryParam('a', 'eh');
            assertEquals('The query string should not contain the a=eh param', 'test.com/?a=1&b=2&c=3', uri.toString());
        }

        function testAddNullParam() {
            var uri = new jsUri('?a=1&b=2&c=3').addQueryParam('d');
            assertEquals('The query string should not contain the null d= param', '?a=1&b=2&c=3&d=', uri.toString());
        }

        function testAddKVPParam() {
            var uri = new jsUri('?a=1&b=2&c=3').addQueryParam('d', '4');
            assertEquals('The query string should not contain the d=4 param', '?a=1&b=2&c=3&d=4', uri.toString());
        }

        function testPrependKVPParam() {
            var uri = new jsUri('?a=1&b=2&c=3').addQueryParam('d', '4', 0);
            assertEquals('The query string should not contain the d=4 param at the beginning', '?d=4&a=1&b=2&c=3', uri.toString());
        }

        function testReplaceQueryParamLongform() {
            var uri = new jsUri('?a=1&b=2&c=3').deleteQueryParam('a').addQueryParam('a', 'eh');
            assertEquals('The query string should contain a=eh at the end', '?b=2&c=3&a=eh', uri.toString());
        }

        function testReplaceQueryParamShortform() {
            var uri = new jsUri('?a=1&b=2&c=3').replaceQueryParam('a', 'eh');
            assertEquals('The query param named a should be modified in place', '?a=eh&b=2&c=3', uri.toString());
        }

        function testReplaceQueryParamNewKey() {
            var uri = new jsUri().replaceQueryParam('page', 2);
            assertEquals('The query should have a new query string', '?page=2', uri.toString());
        }

        /*
            object cloning
        */
        function testClone() {
            var uri = new jsUri('?a=1');
            assertEquals('The clone should have an extended query string', '?a=1&b=2', uri.clone().addQueryParam('b', '2').toString());
            assertEquals('The original should have the original uri', '?a=1', uri.toString());
        }


        /*
            colon as query param separator
        */
        function testColonQueryParamSeparatorRewriting() {
            var uri = new jsUri('www.test.com/?one=1;two=2;three=3&four=4');
            assertEquals('The colons should be replaced by ampersands', 'www.test.com/?one=1&two=2&three=3&four=4', uri.toString());
        }

        function testColonQueryParamSeparatorManipulation() {
            var uri = new jsUri('www.test.com/?one=1;two=2;three=3&four=4')
                .deleteQueryParam('one')
                .addQueryParam('test', 'val', 1);
            assertEquals('The colons should be replaced, the first param should be gone and a new one should be indexed at position 2', 'www.test.com/?two=2&test=val&three=3&four=4', uri.toString());
        }


        /*
            comparing encoded vs. non or partially encoded query param keys and values
        */

        function testUriEncodedComparisonA() {
            var uri = new jsUri('?a=1&this%20is%20a%20multiword%20key=value&c=3')
            assertEquals('Should be able to find the value of the key', 'value', uri.getQueryParamValue('this is a multiword key'));
        }

        function testUriEncodedComparisonB() {
            var uri = new jsUri('?a=1&this%20is%20a%20multiword%20key=value&c=3')
            assertEquals('Should be able to find the value of the key', 'value', uri.getQueryParamValues('this is a multiword key')[0]);
        }

        function testUriEncodedComparisonC() {
            var uri = new jsUri('?a=1&this%20is%20a%20multiword%20key=value&c=3')
                .deleteQueryParam('this is a multiword key');
            assertEquals('The decoded values should match and the param gets deleted', '?a=1&c=3', uri.toString());
        }

        function testUriEncodedComparisonD() {
            var uri = new jsUri('?a=1&b=this is a multiword value&c=3')
                .deleteQueryParam('b', 'this%20is%20a%20multiword%20value');
            assertEquals('The decoded values should match and the param gets deleted', '?a=1&c=3', uri.toString());
        }

        function testUriEncodedComparisonE() {
            var uri = new jsUri('?this is a multiword key=1')
                .replaceQueryParam('this%20is%20a%20multiword%20key', 2);
            assertEquals('The decoded values should match and the param value gets changed', '?this%20is%20a%20multiword%20key=2', uri.toString());
        }

        function testUriEncodedComparisonF() {
            var uri = new jsUri('?this%20is%20a%20multiword%20key=1')
                .replaceQueryParam('this is a multiword key', 2);
            assertEquals('The decoded values should match and the param value gets changed', '?this is a multiword key=2', uri.toString());
        }

        function testUriEncodedComparisonG() {
            var uri = new jsUri('?multi+word=true')
                .replaceQueryParam('multi word', 2);
            assertEquals('The decoded values should match and the param value gets changed', '?multi word=2', uri.toString());
        }

    </script>
</head>
<body>
    <p>
        <a href="jsunit/testRunner.html?testPage=" id="testLink">Click here</a> to launch the JsUnit Test Runner.
    </p>
    <script type="text/javascript">
        var testLink = document.getElementById('testLink');
        testLink.href = testLink.href + window.location;
    </script>
</body>
</html>